<!--
20240814最后修改
@author ljy
对话框公共组件，用于统一对话框的样式。本主键不对对话框的主体部分进行处理
一、使用方法
1.引入组件
import BaseDialog from '@/components/base/dialog/BaseDialog.vue';
2.调用组件
<BaseDialog ref="baseDialogRef" :dialogWidth="title" @closed="closed">
3.定义该组件对象
//定义对话框组件对象
const baseDialogRef = ref();
4.打开和关闭对话框的方法
baseDialogRef.value.openDialog();
baseDialogRef.value.closeDialog();
5.对话框默认提交事件回调
说明：表单提交事件（组件不进行任何提交的实际处理，需要父组件完成）
 （1）基本提交
首先在标签中加入事件 @dialogSubmit="dialogSubmit()"
<BaseDialog ref="baseDialogRef" v-bind="$props" @dialogSubmit="dialogSubmit()">
然后在setup中调用即可
 const dialogSubmit = () => {
  //表单提交代码
}
（1）对话框高级提交事件-例如对话框中包含表单，那就要将表单对象传入
首先在标签中加入事件@dialogSubmit="dialogSubmit(formRef)"
<BaseDialog ref="baseDialogRef" v-bind="$props" @dialogSubmit="dialogSubmit(formRef)">
然后在setup中调用即可
const formRef = ref<FormInstance>(); // 定义表单的ref对象
//执行回调函数
const dialogSubmit = async (formEl: FormInstance | undefined) => {
  console.log(111);
  // 提交表单
  if (!formEl) return;
  // 表单验证
  await formEl.validate(async (valid, fields) => {
    // 如果通过表单验证
    if (valid) {
    }
  });
};
6.对话框关闭事件回调
说明：表单提交事件（组件不进行任何提交的实际处理，需要父组件完成）
 （1）基本提交
 首先在标签中加入事件 @dialogClosed="closed"
  <BaseDialog ref="baseDialogRef" v-bind="$props" :dialogTitle="titleResult" @closed="closed" @dialogSubmit="dialogSubmit(formRef)">
 然后在setup中调用
const closed = () => {
  // 重置表单
  formRef.value!.resetFields();
  // Object.assign(formObject.value, formInitObject);
  // 关闭对话框后还要处理的信息继续传递父组件
  emit('afterCloseDialog');
};
  -->
<template>
  <div class="dialog">
    <el-dialog v-model="dialogVisible" :title="dialogTitle" :width="dialogWidth" :close-on-click-modal="false" @closed="dialogClosed">
      <!-- 
    20240922取消回车自动提交对话框，因为部分表单字段需要回车来进行编辑，如果回车就是提交则会影响体验。
    @submit.prevent
    @keyup.enter="emit('dialogSubmit')" -->
      <template #header>
        <span>{{ dialogTitle }}</span>
        <el-divider class="title_divider" />
      </template>
      <!--对话框主体部分插槽-->
      <!--      <div style="height:70vh;overflow: auto;">-->
      <!-- 下面使用Style接口类型声明会报错（但是不影响实际使用），使用any则不会 -->
      <div :style="dialogBodyStyle">
        <slot name="dialog_body"> </slot>
      </div>
      <template #footer v-if="showDialogFoot">
        <!-- 底部插槽,适合于完全替换底部组件使用 -->
        <slot name="dialog_foot">
          <span class="dialog-footer">
            <el-divider class="foot_divider" />
            <!-- 底部插槽左边,适合于在此新增组件使用 -->
            <slot name="dialog_foot_left"></slot>
            <el-button v-show="showDialogCancelButton" @click="dialogVisible = false">{{ dialogCancelButtonText }}</el-button>
            <el-button v-show="showDialogConfirmButton" type="primary" :loading="loadingButton" @click="emit('dialogSubmit')">{{
              dialogConfirmButtonText
            }}</el-button>
            <!-- 底部插槽右边,适合于在此新增组件使用 -->
            <slot name="dialog_foot_right"> </slot>
          </span>
        </slot>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import type { Style } from '@/types/interface/base_interface';
import { ref } from 'vue';
const emit = defineEmits(['dialogClosed', 'dialogSubmit']);
// 接收父组件的值
interface Props {
  dialogWidth?: string; // 对话框宽度
  dialogTitle?: string; // 对话框标题,前台传入，不用加入添加或编辑的文本。添加或编辑的文本由action属性决定
  showDialogCancelButton?: Boolean; // 是否显示取消按钮
  dialogCancelButtonText?: string; // 取消按钮上的文字
  showDialogConfirmButton?: Boolean; //是否显示确认按钮
  dialogConfirmButtonText?: string; // 确认按钮上的文字
  objectIndialogSubmit?: any; //确认按钮提交事件中的元素(比如表单元素)
  showDialogFoot?: Boolean; // 是否显示对话框脚部
  dialogBodyStyle?: Style; // 对话框主体内容的样式，要求以对象方式传入。也可以用Record<string, any>类型
}
const props = withDefaults(defineProps<Props>(), {
  dialogTitle: '表单',
  dialogWidth: '500px',
  dialogCancelButtonText: '取消',
  showDialogCancelButton: () => Boolean(true),
  showDialogConfirmButton: () => Boolean(true),
  dialogConfirmButtonText: '确定',
  showDialogFoot: () => Boolean(true),
  dialogBodyStyle: () => ({
    height: 'auto', //原来数值是70vh
    overflow: 'auto'
  })
});

// 状态变量
const dialogVisible = ref(false); // 对话框状态栏，true表示对话框可见
let loadingButton = ref(false); // 按钮加载状态，表示在加载中
// 打开此对话框的函数
const openDialog = () => {
  dialogVisible.value = true;
};
// 关闭此对话框的函数
const closeDialog = () => {
  dialogVisible.value = false;
};
// 关闭对话框时候
const dialogClosed = () => {
  // 关闭对话框后还要处理的信息交给父组件
  emit('dialogClosed');
};

defineExpose({
  // 参考vue3官方文档，需要将函数暴露出去才能被父组件调用，setup模式是不暴露的
  openDialog,
  closeDialog
});
</script>

<style lang="scss" scoped>
:deep(.el-dialog__header) {
  /*防止父容器设置了统一的右对齐，导致对话框默认的左对齐变为右对齐。*/
  text-align: left;
}
.dialog {
  :deep(.el-dialog__body) {
    /*修改el-dialog对话框的body样式*/
    padding: 10px 15px; /*element中dialog组件的body默认样式是padding：30px 20px;*/
  }
  .title_divider {
    margin: 20px 0 5px 0;
  }
  .foot_divider {
    margin: 0 0 20px 0;
  }
}
</style>
